package com.sisgh.jefdv1.log;

import com.sisgh.jefdv1.file.LogFileWriter;
import com.sisgh.jefdv1.lang.FormatStringBuilder;
import com.sisgh.jefdv1.util.StringUtils;
import org.slf4j.Marker;

import java.io.Closeable;
import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

public class Logger implements org.slf4j.Logger, Closeable {
    private static final String INFO = "info";
    private static final String WARN = "warn";
    private static final String ERROR = "error";

    private static final String REPLACE_TAG = "{}";

    private static final Logger log;
    private static final LogFileWriter lfw;

    static {
        log = new Logger();
        lfw = LogFileWriter.writer();
    }

    public static Logger logger() {
        return log;
    }

    private void println(String msg) {
        System.out.println(msg);
    }

    private String dateTimePrefix() {
        return LocalDateTime.now().format(DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss"));
    }

    private String format(String format, Object... args) {
        return StringUtils.format(format, REPLACE_TAG, args);
    }

    private String message(String format, String level) {
        FormatStringBuilder fsb = new FormatStringBuilder();

        // 时间 level
        return fsb.appendWithSpace(dateTimePrefix())
                .levelTagWithSpace(level)
                .append(format)
                .toString();
    }

    private String message(String format, String level, Object... args) {
        FormatStringBuilder fsb = new FormatStringBuilder();

        // 时间 level
        return fsb.appendWithSpace(dateTimePrefix())
                .levelTagWithSpace(level)
                .append(format(format, REPLACE_TAG, args))
                .toString();
    }

    private void throwable(Throwable t) {
        lfw.throwable(t);
    }

    public void flush() {
        try {
            lfw.flush();
        } catch (IOException e) {
            println("文件刷写失败");
            throw new RuntimeException(e);
        }
    }

    @Override
    public String getName() {
        return "jefd_log";
    }

    @Override
    public boolean isTraceEnabled() {
        return false;
    }

    @Override
    public void trace(String msg) {
    }

    @Override
    public void trace(String format, Object arg) {
    }

    @Override
    public void trace(String format, Object arg1, Object arg2) {
    }

    @Override
    public void trace(String format, Object... arguments) {
    }

    @Override
    public void trace(String msg, Throwable t) {
    }

    @Override
    public boolean isTraceEnabled(Marker marker) {
        return false;
    }

    @Override
    public void trace(Marker marker, String msg) {
    }

    @Override
    public void trace(Marker marker, String format, Object arg) {
    }

    @Override
    public void trace(Marker marker, String format, Object arg1, Object arg2) {
    }

    @Override
    public void trace(Marker marker, String format, Object... argArray) {

    }

    @Override
    public void trace(Marker marker, String msg, Throwable t) {

    }

    @Override
    public boolean isDebugEnabled() {
        return false;
    }

    @Override
    public void debug(String msg) {

    }

    @Override
    public void debug(String format, Object arg) {

    }

    @Override
    public void debug(String format, Object arg1, Object arg2) {

    }

    @Override
    public void debug(String format, Object... arguments) {

    }

    @Override
    public void debug(String msg, Throwable t) {

    }

    @Override
    public boolean isDebugEnabled(Marker marker) {
        return false;
    }

    @Override
    public void debug(Marker marker, String msg) {

    }

    @Override
    public void debug(Marker marker, String format, Object arg) {

    }

    @Override
    public void debug(Marker marker, String format, Object arg1, Object arg2) {

    }

    @Override
    public void debug(Marker marker, String format, Object... arguments) {

    }

    @Override
    public void debug(Marker marker, String msg, Throwable t) {

    }

    @Override
    public boolean isInfoEnabled() {
        return true;
    }

    private void write(String message) {
        println(message);
        lfw.write(message);
    }

    private void write(String message, Throwable t) {
        println(message);
        lfw.write(message);
        throwable(t);
    }

    @Override
    public void info(String msg) {
        String message = message(msg, INFO);
        write(message);
    }

    @Override
    public void info(String format, Object arg) {
        String message = message(format, INFO, arg);
        write(message);
    }

    @Override
    public void info(String format, Object arg1, Object arg2) {
        String message = message(format, INFO, arg1, arg2);
        write(message);
    }

    @Override
    public void info(String format, Object... arguments) {
        String message = message(format, INFO, arguments);
        write(message);
    }

    @Override
    public void info(String msg, Throwable t) {
        String message = message(msg, INFO);
        write(message, t);
    }

    @Override
    public boolean isInfoEnabled(Marker marker) {
        return false;
    }

    @Override
    public void info(Marker marker, String msg) {

    }

    @Override
    public void info(Marker marker, String format, Object arg) {

    }

    @Override
    public void info(Marker marker, String format, Object arg1, Object arg2) {

    }

    @Override
    public void info(Marker marker, String format, Object... arguments) {

    }

    @Override
    public void info(Marker marker, String msg, Throwable t) {

    }

    @Override
    public boolean isWarnEnabled() {
        return true;
    }

    @Override
    public void warn(String msg) {
        String message = message(msg, WARN);
        write(message);
    }

    @Override
    public void warn(String format, Object arg) {
        String message = message(format, WARN, arg);
        write(message);
    }

    @Override
    public void warn(String format, Object... arguments) {
        String message = message(format, WARN, arguments);
        write(message);
    }

    @Override
    public void warn(String format, Object arg1, Object arg2) {
        String message = message(format, WARN, arg1, arg2);
        write(message);
    }

    @Override
    public void warn(String msg, Throwable t) {
        String message = message(msg, WARN);
        write(message, t);
    }

    @Override
    public boolean isWarnEnabled(Marker marker) {
        return false;
    }

    @Override
    public void warn(Marker marker, String msg) {

    }

    @Override
    public void warn(Marker marker, String format, Object arg) {

    }

    @Override
    public void warn(Marker marker, String format, Object arg1, Object arg2) {

    }

    @Override
    public void warn(Marker marker, String format, Object... arguments) {

    }

    @Override
    public void warn(Marker marker, String msg, Throwable t) {

    }

    @Override
    public boolean isErrorEnabled() {
        return true;
    }

    @Override
    public void error(String msg) {
        String message = message(msg, ERROR);
        write(message);
    }

    @Override
    public void error(String format, Object arg) {
        String message = message(format, ERROR, arg);
        write(message);
    }

    @Override
    public void error(String format, Object arg1, Object arg2) {
        String message = message(format, ERROR, arg1, arg2);
        write(message);
    }

    @Override
    public void error(String format, Object... arguments) {
        String message = message(format, ERROR, arguments);
        write(message);
    }

    @Override
    public void error(String msg, Throwable t) {
        String message = message(msg, ERROR);
        write(message, t);
    }

    @Override
    public boolean isErrorEnabled(Marker marker) {
        return false;
    }

    @Override
    public void error(Marker marker, String msg) {

    }

    @Override
    public void error(Marker marker, String format, Object arg) {

    }

    @Override
    public void error(Marker marker, String format, Object arg1, Object arg2) {

    }

    @Override
    public void error(Marker marker, String format, Object... arguments) {

    }

    @Override
    public void error(Marker marker, String msg, Throwable t) {

    }

    @Override
    public void close() {
        try {
            lfw.close();
        } catch (IOException e) {
            println("LogFileWriter close失败");
            throw new RuntimeException(e);
        }
    }
}
